import { Nodes, dom } from '@knno/dom';
import { DATA } from '../symbol';
import { formCellStyle } from './form.css';
import { Container } from '../interface';
import SVGRequired from '../../svg/astrisk.svg';
import SVGHelp from '@material-design-icons/svg/filled/help.svg';
import { getColumns } from './form';

export class FormCell extends Container {
	private [DATA]: { col: number | null; row: number | null; colspan: number[]; rowspan: number[] };

	protected get box(): Nodes {
		return this.query(':scope>div.content');
	}

	constructor() {
		const caption = dom.div('caption').append(dom.span('asterisk'), dom.span('txt'), dom.span('help'));
		const box = dom.div('content');
		const notice = dom.div('notice');
		super(dom.div(formCellStyle).append(caption, box, notice));
		this[DATA] = {
			col: null,
			row: null,
			colspan: [1],
			rowspan: [1],
		};
		this.on('formcolumnchanged', () => {
			this.calculate();
		});
	}

	required(): boolean;
	required(value: boolean): this;
	required(value?: boolean): boolean | this {
		const div = this.query(':scope>div.caption');
		if (value === undefined) {
			return div.attr('required') != null;
		}
		const req = div.attr('required') != null;
		div.attr('required', value);
		if (value && !req) {
			this.query(':scope>div.caption>span.asterisk').insert(dom.html(SVGRequired));
		} else {
			this.query(':scope>div.caption>span.asterisk>svg').detach();
		}
		return this;
	}

	caption(): string;
	caption(text: string): this;
	caption(text?: string): this | string | undefined {
		const div = this.query(':scope>div.caption>span.txt');
		if (typeof text === 'string') {
			div.text(text);
			return this;
		}
		return div.text();
	}

	help(): string;
	help(text: string): this;
	help(text?: string): this | string | undefined {
		const div = this.query(':scope>div.caption>span.help');
		if (typeof text === 'string') {
			if (text) {
				div.html(SVGHelp);
			} else {
				div.html('');
			}
			div.attr('title', text);
			return this;
		}
		return div.attr('title') ?? '';
	}

	notice(): string;
	notice(text: string): this;
	notice(text?: string): this | string | undefined {
		const div = this.query(':scope>div.notice');
		if (typeof text === 'string') {
			div.text(text);
			return this;
		}
		return div.text();
	}

	private calculate() {
		let cols = parseInt(this.parent().attr('cols') ?? '1');
		if (isNaN(cols)) cols = 1;
		let mode = parseInt(this.parent().attr('mode') ?? '0');
		if (isNaN(mode)) mode = 0;
		const colspan = Math.min(this[DATA].colspan[mode], cols);
		const rowspan = this[DATA].rowspan[mode];
		let col: string;
		if (this[DATA].col !== null) {
			col = `${this[DATA].col} / span ${colspan}`;
		} else {
			col = `span ${colspan}`;
		}
		this.css('gridColumn', col);
		let row: string;
		if (this[DATA].row !== null) {
			row = `${this[DATA].row} / span ${rowspan}`;
		} else {
			row = `span ${rowspan}`;
		}
		this.css('gridRow', row);
	}

	col(): number | null;
	col(value: number | null): this;
	col(value?: number | null): this | number | null {
		if (value === undefined) {
			return this[DATA].col;
		}
		this[DATA].col = value === null ? null : Math.max(1, value);
		this.calculate();
		return this;
	}

	row(): number | null;
	row(value: number | null): this;
	row(value?: number | null): this | number | null {
		if (value === undefined) {
			return this[DATA].row;
		}
		this[DATA].row = value === null ? null : Math.max(1, value);
		this.calculate();
		return this;
	}

	colspan(value: string): this {
		this[DATA].colspan = getColumns(value);
		this.calculate();
		return this;
	}

	rowspan(value: string): this {
		this[DATA].rowspan = getColumns(value);
		this.calculate();
		return this;
	}
}

export function formCell(...className: string[]): FormCell {
	return new FormCell().addClass(...className);
}
